﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Kiiro.Common.Entities;
using Kiiro.DataAccess;
using Kiiro.Validation.Validators.Entities;
using Kiiro.Common.Utility;
using Microsoft.SharePoint;
using Kiiro.ExceptionManagement;
using System.Web.UI.WebControls;

namespace Kiiro.Model
{
    public static class DocumentModel
    {
        public static Document GetDocumentById(int id, Guid siteCollectionId, string serverRelativeUrl)
        {
            return DocumentDA.Instance.GetDocumentById(id, siteCollectionId, serverRelativeUrl);
        }

        public static Document GetDocumentByUrl(string documentUrl, int documentId,Guid siteCollectionId, string serverRelativeUrl)
        {
            return DocumentDA.Instance.GetDocumentByUrl(documentUrl, documentId, siteCollectionId, serverRelativeUrl);
        }


        public static List<Document> GetAllDocuments ( Guid siteCollectionId, string serverRelativeUrl )
        {
            return DocumentDA.Instance.GetAllDocuments ( siteCollectionId, serverRelativeUrl );
        }

        public static List<Document> GetDocumentsByIds ( List<int> documentIds, Guid siteCollectionId, string serverRelativeUrl )
        {
            return DocumentDA.Instance.GetDocumentsByIds ( documentIds, siteCollectionId, serverRelativeUrl );
        }
        
        public static List<Document> GetDocumentsByUrls ( List<string> documentUrls, Guid siteCollectionId, string serverRelativeUrl )
        {
            return DocumentDA.Instance.GetDocumentsByUrls ( documentUrls, siteCollectionId, serverRelativeUrl );
        }





        public static List<Document> GetDocumentsByFolder(Guid siteCollectionId, string serverRelativeUrl, string folderWebRelativeUrl)
        {
            return DocumentDA.Instance.GetDocumentsByFolder(siteCollectionId, serverRelativeUrl, folderWebRelativeUrl);
        }

        public static List<Document> GetDocumentVersions(int id, Guid siteCollectionid, string serverRelativeUrl)
        {
            return DocumentDA.Instance.GetDocumentVersions(id, siteCollectionid, serverRelativeUrl);
        }

        public static List<Document> GetDocumentVersions(string documentUrl,int documentId, Guid siteCollectionid, string serverRelativeUrl)
        {
            return DocumentDA.Instance.GetDocumentVersions(documentUrl, documentId, siteCollectionid, serverRelativeUrl);
        }

        public static Document Save ( Document document, List<int> usersToNotify, User currentUser, Guid siteCollectionId, string serverRelativeUrl )
        {
            new DocumentValidator ( ).Validate ( document );

            if ( document.IsValid ( ) || document.EditType == EditType.Deleted )
            {
                Midori midori = new Midori ( );
                List<Document> docsList = new List<Document> ( );

                if ( document.EditType == EditType.Deleted )
                {
                    document = DocumentDA.Instance.GetDocumentById ( document.Id, siteCollectionId, serverRelativeUrl );
                    document.EditType = EditType.Deleted;
                }

                if ( document.IsFolder )
                {
                    string folderWebUrl = document.ServerRelativeUrl;
                    docsList.Add ( document );
                    midori.Documents = GetAllDocumentsFromFolderAndSubFolders ( docsList, document, siteCollectionId, serverRelativeUrl, folderWebUrl );
                }
                else
                {
                    midori.Documents.Add ( document );
                }
                midori = Save ( midori, usersToNotify, currentUser, siteCollectionId, serverRelativeUrl );

                if ( midori.Documents.Count > 0 )
                    document = midori.Documents [ 0 ];
            }

            return document;
        }

        public static Midori Save ( Midori midori, List<int> usersToNotify, User currentUser, Guid siteCollectionId, string serverRelativeUrl )
        {
            try
            {
                List<Document> savedDocuments = new List<Document> ( );

                foreach ( Document document in midori.Documents )
                {
                    document.SiteCollectionId = siteCollectionId;
                    new DocumentValidator ( ).Validate ( document );

                    if ( document.IsValid ( ) || document.EditType == EditType.Deleted )
                    {
                        PermissionsModel.GetGlobalPermissionBitsForCurrentUser ( document, currentUser, siteCollectionId, serverRelativeUrl, false );

                        if ( document.PermissionBitsDiscussions != null && document.PermissionBitsDiscussions.Count > 0 &&
                            ( document.PermissionBitsDiscussions [ 0 ] || document.PermissionBitsDiscussions [ 2 ] || document.PermissionBitsDiscussions [ 3 ] ) )
                        {
                            if ( document.EditType == EditType.Deleted )
                                DocumentDA.Instance.Save ( document, siteCollectionId, serverRelativeUrl );
                            else
                                savedDocuments.Add ( DocumentDA.Instance.Save ( document, siteCollectionId, serverRelativeUrl ) );
                        }
                    }
                }

                if ( savedDocuments.Count > 0 && usersToNotify != null && usersToNotify.Count > 0 )
                {
                    SendNewDocumentNotification ( savedDocuments, usersToNotify, siteCollectionId, serverRelativeUrl, currentUser );
                }
            }
            catch ( Exception ex )
            {
                ExceptionManager.HandleException ( ex, true );
            }

            return midori;
        }

        private static List<Document> GetAllDocumentsFromFolderAndSubFolders ( List<Document> docsList, Document document, Guid siteCollectionId, string serverRelativeUrl, string folderWebUrl )
        {
            using ( SPWeb web = SPHelpers.GetWeb ( siteCollectionId, serverRelativeUrl ) )
            {
                SPFolder rootFolder = web.GetFolder ( folderWebUrl );

                if ( rootFolder.SubFolders.Count > 0 )
                {
                    foreach ( SPFolder subFolder in rootFolder.SubFolders )
                    {
                        Document folder = SPDataHelpers.MakeDocumentFromFolderItem ( subFolder.Item );
                        folder.EditType = document.EditType;
                        docsList.Insert ( 0, folder );
                        docsList = GetAllDocumentsFromFolderAndSubFolders ( docsList, document, siteCollectionId, serverRelativeUrl, subFolder.ServerRelativeUrl );
                    }
                }

                foreach ( SPFile file in rootFolder.Files )
                {
                    if ( file.Item != null )
                    {
                        Document doc = SPDataHelpers.MakeDocumentFromFileItem ( file.Item );
                        doc.CreatedBy = UserModel.GetUserByLogin ( doc.CreatedBy.Login, siteCollectionId, serverRelativeUrl );
                        doc.ModifiedBy = UserDA.Instance.GetUserByLogin ( doc.ModifiedBy.Login, siteCollectionId, serverRelativeUrl );
                        doc.EditType = document.EditType;
                        docsList.Insert ( 0, doc );
                    }
                }
            }

            return docsList;
        }

        public static Document RestoreVersion ( int documentId, string versionLabel, User currentUser, Guid siteCollectionId, string serverRelativeUrl )
        {
            Document document = DocumentDA.Instance.GetDocumentById ( documentId, siteCollectionId, serverRelativeUrl );

            PermissionsModel.GetGlobalPermissionBitsForCurrentUser ( document, currentUser, siteCollectionId, serverRelativeUrl, false );

            if ( document.PermissionBitsDocuments != null && document.PermissionBitsDocuments.Count > 0 &&
                ( document.PermissionBitsDocuments [ 0 ] || document.PermissionBitsDocuments [ 2 ] || document.PermissionBitsDocuments [ 3 ] ) )
            {
                document = DocumentDA.Instance.RestoreVersion ( document, versionLabel, siteCollectionId, serverRelativeUrl );
            }

            return document;
        }

        public static void SendNewDocumentNotification(List<Document> documents, List<int> usersToNotify, Guid siteCollectionId, string serverRelativeUrl, User currentUser)
        {
            if (usersToNotify.Count > 0)
            {
                string webUrl;
                string webTitle;
                using (SPWeb web = SPHelpers.GetWeb(siteCollectionId, serverRelativeUrl))
                {
                    webUrl = web.Url;
                    webTitle = web.Title;
                }

                List<User> users = UserModel.GetUsersByIds(usersToNotify, siteCollectionId, serverRelativeUrl);

                foreach (User user in users)
                {
                    string documentLinks = "";
                    webUrl = EmailModel.Instance.FixUrlForUserZone(webUrl, user);

                    foreach (Document document in documents)
                    {
                        string documentUrl = EmailModel.Instance.FixUrlForUserZone(webUrl + "/" + document.Url, user);
                        documentLinks += string.Format("<a href='{0}'>{0}</a><br />", documentUrl);
                    }

                    string[] args = new string[] { webTitle, webUrl, documentLinks };

                    EmailModel.Instance.SendNotificationEmail(EmailModel.EmailType.DocumentUpload, user.Email, args, currentUser);
                }
            }
        }

        public static string SaveProjectPlan ( Project project, Guid siteCollectionId, string serverRelativeUrl )
        {
            string projectRelativeUrl = serverRelativeUrl.StartsWith ( "/" ) ? serverRelativeUrl : "/" + serverRelativeUrl;
            string projectPlanFileUrl = default ( string );

            if ( project != null )
            {
                try
                {
                    List<Attachment> attachemnts = project.AttachmentList;

                    if ( attachemnts.Count > 0 )
                    {
                        foreach ( Attachment attachment in attachemnts )
                        {
                            Document projectPlanDoc = new Document ( );

                            projectPlanDoc.EditType = attachment.EditType;
                            projectPlanDoc.IsFolder = false;
                            projectPlanDoc.IsProjectPlan = true;

                            projectPlanDoc.Title = attachment.FileName;
                            projectPlanDoc.FileBytes = attachment.Bytes;

                            if ( attachment.EditType == EditType.Created )
                            {
                                projectPlanDoc.Description = String.Format ( "Project Plan for {0}", project.Title );
                            }

                            projectPlanDoc.ServerRelativeUrl = projectRelativeUrl;
                            projectPlanDoc.SiteCollectionId = siteCollectionId;
                            projectPlanDoc.FolderUrl = projectRelativeUrl + Constants.SPListUrls.Documents;
                            projectPlanDoc.Url = projectPlanDoc.FolderUrl + "/" + projectPlanDoc.Title;

                            projectPlanDoc = DocumentDA.Instance.Save ( projectPlanDoc, siteCollectionId, projectRelativeUrl );

                            if ( attachment.EditType != EditType.Deleted )
                                projectPlanFileUrl = String.Format ( "{0}/{1}", projectPlanDoc.ServerRelativeUrl, projectPlanDoc.Title );
                        }
                    }
                    else
                    {
                        projectPlanFileUrl = project.ProjectPlanFileUrl;
                    }
                }
                catch ( Exception ex )
                {
                    ExceptionManager.HandleException ( ex, true );
                }
            }

            return projectPlanFileUrl;
        }

        public static Document MoveDocument ( int itemId, string destination, Guid siteCollectionId, string serverRelativeUrl )
        {
            Document document = DocumentDA.Instance.GetDocumentById ( itemId, siteCollectionId, serverRelativeUrl );
            
            string newUrl = string.Format ( "{0}/{1}/{2}", serverRelativeUrl, destination, document.Title );

            Document existingDocument = DocumentDA.Instance.GetDocumentByUrl ( newUrl, 0, siteCollectionId, serverRelativeUrl );

            if ( existingDocument == null )
                DocumentDA.Instance.MoveDocument ( itemId, destination, siteCollectionId, serverRelativeUrl );
            else
            {
                if ( document.Id == existingDocument.Id )
                    document.FileMessage.Add ( new ValidationMessage ( ValidationSeverity.Validation, "Unable to move file.<br />Target destination folder is current folder." ) );
                else
                {
                    if (document.IsFolder)
                        document.FileMessage.Add ( new ValidationMessage ( ValidationSeverity.Validation, "Unable to move folder.<br />A file or folder with the same name already exists in the target destination folder." ) );
                    else
                        document.FileMessage.Add ( new ValidationMessage ( ValidationSeverity.Validation, "Unable to move file.<br />A file or folder with the same name already exists in the target destination folder." ) );
                }
            }

            return document;
        }        

        public static List<string> GetAllFolders(Guid siteCollectionId, string serverRelativeUrl)
        {
            List<string> folders = null;
            
            SPFolder documents = DocumentDA.Instance.GetAllFolders(siteCollectionId, serverRelativeUrl);

            if (documents != null)
            {
                folders = new List<string>();
                folders.Add(documents.Url);
                GetSubFolders(documents, folders);
            }

            folders.Sort();

            return folders;
        }

        public static void GetSubFolders(SPFolder folders, List<string> foldersList)
        {
            if (folders.SubFolders != null)
            {
                foreach (SPFolder folder in folders.SubFolders)
                {
                    if (folder.Url != "Documents/Forms")
                    {
                        foldersList.Add(folder.Url);
                        GetSubFolders(folder, foldersList);
                    }
                }
            }
        }
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.Model/DocumentModel.cs $
 * 
 * 32    2/08/10 5:04p Camerons
 * 
 * 31    2/08/10 12:00p Camerons
 * 
 * 30    1/25/10 1:17p Camerons
 * 
 * 29    1/21/10 2:40p Camerons
 * 
 * 28    1/20/10 3:04p Camerons
 * 
 * 27    1/12/10 12:03p Camerons
 * 
 * 26    26/11/09 10:35a Camerons
 * 
 * 25    11/26/09 10:12a Stefanf
 * 
 * 24    17/11/09 6:46p Camerons
 * 
 * 23    10/11/09 11:40a Camerons
 * 
 * 22    9/11/09 9:00p Camerons
 * 
 * 21    9/11/09 1:18p Camerons
 * 
 * 20    8/11/09 3:00p Camerons
 * 
 * 19    28/10/09 11:18a Tobys
 * 
 * 18    10/27/09 6:39p Adamw
 * fixed some issues around deleting plan files and saving project
 * settings
 * 
 * 17    10/27/09 5:53p Adamw
 * accomodations for moving plan file to document library:
 * -moved saving of plan out of ProjectsDA and into DocumentModel -->
 * DocumentDA
 * -added call to save project plan file to document library from
 * ProjectsModel
 * -changed New/Edit Project pages to pass in Attachment collection
 * 
 * 16    10/22/09 12:55p Adamw
 * 
 * 15    10/22/09 12:52p Adamw
 * Case 344, added CurrentUser to Model call (needed for permissions
 * check) and changed to check document CUD permissions
 * 
 * 14    10/21/09 6:48p Adamw
 * Case 345, changed subfolders and subfiles to use the same EditType as
 * root document object, changed the rename of the folder to the
 * recommended approach of using folder.MoveTo instead of a field value
 * change (metadata is kept)
 * 
 * 13    10/19/09 12:23p Adamw
 * Case 297, added null check to Save before sending notifications
 * 
 * 12    10/02/09 10:46a Stefanf
 * 
 * 11    30/09/09 9:31a Shafia
 * 
 * 10    21/09/09 3:30p Camerons
 * First batch of changes for 1.1.x.x - Security groups update
 * 
 * 9     17/08/09 10:29a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/